/**
 * @file        mem_alloc.c
 * @brief       XXXX
 * @note        XXXX
 * @author      靳普诏(puzhao.jin@hopechart.com)
 * @date        2025/09/17
 * @version     1.0

 * @par         修改日志
 * <table>
 * <tr><th>Date         <th>Version     <th>Author      <th> Description
 * <tr><td>2025/09/17   <td>1.0         <td>靳普诏       <td> 创建初始版本
 * @copyright 杭州鸿泉物联网技术股份有限公司
 */
 
#include "az_clib/ds/mem_alloc.h"
#include <string.h>

/**
 * @brief 内存块头部结构体
 * @note  每个分配的内存块前都有此头部信息
 */
typedef struct TMemBlockTag
{
    UInt32 size;                    ///< 内存块大小（不包括头部）
    Bool   is_free;                 ///< 是否为空闲块
    struct TMemBlockTag *next;      ///< 指向下一个内存块
    struct TMemBlockTag *prev;      ///< 指向上一个内存块
} TMemBlock;

/**
 * @brief 内存分配器控制结构体
 */
typedef struct
{
    void      *pool_start;          ///< 内存池起始地址
    UInt32     pool_size;           ///< 内存池总大小
    TMemBlock *first_block;         ///< 第一个内存块
    TMemBlock *last_block;          ///< 最后一个内存块
    Bool       is_initialized;      ///< 是否已初始化
    UInt32     allocated_count;     ///< 已分配块数量
    UInt32     free_count;          ///< 空闲块数量
} TMemAllocCtrl;

/**
 * @brief 全局内存分配器控制变量
 */
static TMemAllocCtrl g_mem_ctrl = {0};

/**
 * @brief 内存对齐大小（4字节对齐）
 */
#define MEM_ALIGN_SIZE      4
#define MEM_ALIGN_MASK      (MEM_ALIGN_SIZE - 1)

/**
 * @brief 内存块头部大小
 */
#define MEM_BLOCK_HEADER_SIZE    sizeof(TMemBlock)

/**
 * @brief 最小分配大小
 */
#define MEM_MIN_ALLOC_SIZE       8

/**
 * @brief 内存对齐宏
 * @param size 要对齐的大小
 * @return 对齐后的大小
 */
#define MEM_ALIGN(size)     (((size) + MEM_ALIGN_MASK) & (~MEM_ALIGN_MASK))

/**
 * @brief 合并相邻的空闲内存块
 * @param block 要合并的内存块
 */
static void merge_free_blocks(TMemBlock *block)
{
    if (block == NULL || !block->is_free)
    {
        return;
    }
    
    // 向后合并
    while (block->next && block->next->is_free)
    {
        TMemBlock *next_block = block->next;
        block->size += next_block->size + MEM_BLOCK_HEADER_SIZE;
        block->next = next_block->next;
        
        if (next_block->next)
        {
            next_block->next->prev = block;
        }
        else
        {
            g_mem_ctrl.last_block = block;
        }
        
        g_mem_ctrl.free_count--;
    }
    
    // 向前合并
    while (block->prev && block->prev->is_free)
    {
        TMemBlock *prev_block = block->prev;
        prev_block->size += block->size + MEM_BLOCK_HEADER_SIZE;
        prev_block->next = block->next;
        
        if (block->next)
        {
            block->next->prev = prev_block;
        }
        else
        {
            g_mem_ctrl.last_block = prev_block;
        }
        
        block = prev_block;
        g_mem_ctrl.free_count--;
    }
}

/**
 * @brief 分割内存块
 * @param block 要分割的内存块
 * @param size  需要的大小
 * @return 分割后的新块指针，失败返回NULL
 */
static TMemBlock* split_block(TMemBlock *block, UInt32 size)
{
    if (block == NULL || !block->is_free)
    {
        return NULL;
    }
    
    UInt32 aligned_size = MEM_ALIGN(size);
    
    // 如果剩余空间不足以创建新块，则不分割
    if (block->size < aligned_size + MEM_BLOCK_HEADER_SIZE + MEM_MIN_ALLOC_SIZE)
    {
        return block;
    }
    
    // 创建新的空闲块
    TMemBlock *new_block = (TMemBlock*)((UInt8*)block + MEM_BLOCK_HEADER_SIZE + aligned_size);
    new_block->size = block->size - aligned_size - MEM_BLOCK_HEADER_SIZE;
    new_block->is_free = True;
    new_block->next = block->next;
    new_block->prev = block;
    
    // 更新原块
    block->size = aligned_size;
    block->next = new_block;
    
    // 更新下一个块的prev指针
    if (new_block->next)
    {
        new_block->next->prev = new_block;
    }
    else
    {
        g_mem_ctrl.last_block = new_block;
    }
    
    g_mem_ctrl.free_count++;
    
    return block;
}

/**
 * @brief 查找合适的空闲内存块
 * @param size 需要的大小
 * @return 找到的内存块指针，失败返回NULL
 */
static TMemBlock* find_free_block(UInt32 size)
{
    TMemBlock *current = g_mem_ctrl.first_block;
    UInt32 aligned_size = MEM_ALIGN(size);
    
    // 首次适应算法
    while (current != NULL)
    {
        if (current->is_free && current->size >= aligned_size)
        {
            return split_block(current, aligned_size);
        }
        current = current->next;
    }
    
    return NULL;
}

Bool AzMemAllocInit(void *buff, Int32 size)
{
    // 参数有效性检查
    if (buff == NULL || size <= (Int32)(MEM_BLOCK_HEADER_SIZE + MEM_MIN_ALLOC_SIZE))
    {
        return False;
    }
    
    // 防止重复初始化
    if (g_mem_ctrl.is_initialized)
    {
        return False;
    }
    
    // 初始化控制结构
    g_mem_ctrl.pool_start = buff;
    g_mem_ctrl.pool_size = (UInt32)size;
    g_mem_ctrl.allocated_count = 0;
    g_mem_ctrl.free_count = 1;
    g_mem_ctrl.is_initialized = True;
    
    // 创建第一个空闲块
    g_mem_ctrl.first_block = (TMemBlock*)buff;
    g_mem_ctrl.last_block = g_mem_ctrl.first_block;
    
    g_mem_ctrl.first_block->size = size - MEM_BLOCK_HEADER_SIZE;
    g_mem_ctrl.first_block->is_free = True;
    g_mem_ctrl.first_block->next = NULL;
    g_mem_ctrl.first_block->prev = NULL;
    
    return True;
}

Bool AzMemAllocDone(void)
{
    if (!g_mem_ctrl.is_initialized)
    {
        return False;
    }
    
    // 检查是否还有未释放的内存
    if (g_mem_ctrl.allocated_count > 0)
    {
        return False;
    }
    
    // 清空控制结构
    memset(&g_mem_ctrl, 0, sizeof(TMemAllocCtrl));
    
    return True;
}

void *AzMemAlloc(Int32 size)
{
    // 参数和状态检查
    if (!g_mem_ctrl.is_initialized || size <= 0)
    {
        return NULL;
    }
    
    UInt32 alloc_size = (UInt32)size;
    if (alloc_size < MEM_MIN_ALLOC_SIZE)
    {
        alloc_size = MEM_MIN_ALLOC_SIZE;
    }
    
    // 查找合适的空闲块
    TMemBlock *block = find_free_block(alloc_size);
    if (block == NULL)
    {
        return NULL;
    }
    
    // 标记为已分配
    block->is_free = False;
    g_mem_ctrl.allocated_count++;
    g_mem_ctrl.free_count--;
    
    // 返回用户数据区域指针
    return (void*)((UInt8*)block + MEM_BLOCK_HEADER_SIZE);
}

void AzMemFree(void *ptr)
{
    // 参数和状态检查
    if (ptr == NULL || !g_mem_ctrl.is_initialized)
    {
        return;
    }
    
    // 获取内存块头部
    TMemBlock *block = (TMemBlock*)((UInt8*)ptr - MEM_BLOCK_HEADER_SIZE);
    
    // 边界检查
    if ((UInt8*)block < (UInt8*)g_mem_ctrl.pool_start || 
        (UInt8*)block >= (UInt8*)g_mem_ctrl.pool_start + g_mem_ctrl.pool_size)
    {
        return; // 指针不在内存池范围内
    }
    
    // 检查是否已经是空闲块
    if (block->is_free)
    {
        return; // 避免重复释放
    }
    
    // 标记为空闲
    block->is_free = True;
    g_mem_ctrl.allocated_count--;
    g_mem_ctrl.free_count++;
    
    // 合并相邻的空闲块
    merge_free_blocks(block);
}

void *AzMemRealloc(void *ptr, Int32 size)
{
    // 特殊情况处理
    if (ptr == NULL)
    {
        return AzMemAlloc(size);
    }
    
    if (size == 0)
    {
        AzMemFree(ptr);
        return NULL;
    }
    
    if (!g_mem_ctrl.is_initialized)
    {
        return NULL;
    }
    
    // 获取原内存块
    TMemBlock *old_block = (TMemBlock*)((UInt8*)ptr - MEM_BLOCK_HEADER_SIZE);
    
    // 边界检查
    if ((UInt8*)old_block < (UInt8*)g_mem_ctrl.pool_start || 
        (UInt8*)old_block >= (UInt8*)g_mem_ctrl.pool_start + g_mem_ctrl.pool_size ||
        old_block->is_free)
    {
        return NULL;
    }
    
    UInt32 new_size = MEM_ALIGN((UInt32)size);
    UInt32 old_size = old_block->size;
    
    // 如果新大小小于等于原大小，尝试分割
    if (new_size <= old_size)
    {
        if (old_size - new_size >= MEM_BLOCK_HEADER_SIZE + MEM_MIN_ALLOC_SIZE)
        {
            split_block(old_block, new_size);
        }
        return ptr;
    }
    
    // 检查能否向后扩展
    if (old_block->next && old_block->next->is_free)
    {
        UInt32 total_size = old_size + old_block->next->size + MEM_BLOCK_HEADER_SIZE;
        if (total_size >= new_size)
        {
            // 合并下一个空闲块
            TMemBlock *next_block = old_block->next;
            old_block->size = total_size;
            old_block->next = next_block->next;
            
            if (next_block->next)
            {
                next_block->next->prev = old_block;
            }
            else
            {
                g_mem_ctrl.last_block = old_block;
            }
            
            g_mem_ctrl.free_count--;
            
            // 分割多余部分
            if (total_size - new_size >= MEM_BLOCK_HEADER_SIZE + MEM_MIN_ALLOC_SIZE)
            {
                split_block(old_block, new_size);
            }
            
            return ptr;
        }
    }
    
    // 无法原地扩展，分配新内存并复制
    void *new_ptr = AzMemAlloc(size);
    if (new_ptr == NULL)
    {
        return NULL;
    }
    
    // 复制原数据
    UInt32 copy_size = (old_size < new_size) ? old_size : new_size;
    memcpy(new_ptr, ptr, copy_size);
    
    // 释放原内存
    AzMemFree(ptr);
    
    return new_ptr;
}






/**
 * @brief       初始化内存分配器
 * @param[in]   buff  用于内存分配的缓冲区指针
 * @param[in]   size  缓冲区大小（字节数）
 * @return      Bool  初始化结果
 * @retval      True  初始化成功
 * @retval      False 初始化失败（参数无效或已初始化）
 * @note        必须在使用其他内存分配函数前调用此函数
 * @warning     buff指向的内存区域在分配器生命周期内不能被释放
 */
Bool AzMemAllocInit(void *buff, Int32 size);

/**
 * @brief       反初始化内存分配器
 * @return      Bool  反初始化结果
 * @retval      True  反初始化成功
 * @retval      False 反初始化失败（未初始化或仍有内存未释放）
 * @note        调用后将释放所有分配的内存，使分配器回到未初始化状态
 * @warning     确保所有分配的内存都已正确释放后再调用此函数
 */
Bool AzMemAllocDone(void);

/**
 * @brief       分配指定大小的内存块
 * @param[in]   size  要分配的内存大小（字节数）
 * @return      void* 分配的内存块指针
 * @retval      非NULL 分配成功，返回内存块起始地址
 * @retval      NULL   分配失败（内存不足、未初始化或参数无效）
 * @note        分配的内存内容未初始化，使用前需要设置初值
 * @warning     分配的内存必须通过AzMemFree释放，避免内存泄漏
 */
void *AzMemAlloc(Int32 size);

/**
 * @brief       释放指定的内存块
 * @param[in]   ptr   要释放的内存块指针
 * @return      void  无返回值
 * @note        ptr必须是通过AzMemAlloc或AzMemRealloc分配的有效指针
 * @warning     释放后不要再访问该内存区域，避免野指针错误
 * @warning     对同一指针多次调用释放或释放无效指针将导致未定义行为
 */
void  AzMemFree(void *ptr);

/**
 * @brief       重新分配内存块大小
 * @param[in]   ptr   原内存块指针（可以为NULL）
 * @param[in]   size  新的内存大小（字节数）
 * @return      void* 重新分配的内存块指针
 * @retval      非NULL 重新分配成功，返回新内存块起始地址
 * @retval      NULL   重新分配失败（内存不足、未初始化或参数无效）
 * @note        如果ptr为NULL，行为等同于AzMemAlloc(size)
 * @note        如果size为0，行为等同于AzMemFree(ptr)并返回NULL
 * @note        原内存内容在新大小范围内会被保留
 * @warning     返回的指针可能与原指针不同，必须使用新返回的指针
 * @warning     如果重新分配失败，原内存块保持不变且仍然有效
 */
void *AzMemRealloc(void *ptr, Int32 size);







///< Generated on "2025-09-17 22:28:49" by the tool "gen_hq_file.py >> V20231119" 

